#include <stdio.h>
#include <stdlib.h>
#define N 10

typedef struct student // 设置一个结构体存放学号，学生名字，课程分数
{
    long studentID;
    char studentName[20];
    float score[3];
} STUDENT;

char CourseName[][20] = {"Porgramming", "English", "Math"}; // 通过全局变量规定科目名称

void input(STUDENT stu_inf[], int n);                       // 输入学生信息，n为学生人数
void PrintCourseAverage(float ave_course[], int m);         // 输出各科目的平均分,m为科目的数量
void average(STUDENT stu_inf[], int n, float ave_course[]); // 计算各科平均分，把各科目的平均分记录在ave_course数组中，n为学生人数
int find(STUDENT stu_inf[], int n, int key);                // 使用二分法查找学号为key的学生下标，如果找到则返回下标，如果找不到则返回-1，注意学生信息输入时需保证按学号顺序输入学生信息。

int main()
{
    STUDENT stuarray[N];
    int n;
    float aver[3]; // 创建三门课程的平均分数组

    printf("Please enter students' number:\n ");
    scanf("%d", &n);    // 输入学生个数
    input(stuarray, n); // 输入n个学生的结构体数组
    average(stuarray, n, aver);
    PrintCourseAverage(aver, 3);

    long stuID;
    printf("Please input student ID you want to search for:\n ");
    scanf("%ld", &stuID); // 输入想要查找的学号
    int pos = find(stuarray, n, stuID);
    if (pos == -1)
        printf("No Found!"); // 没有找到相应的学生
    else
        printf("Student id is %d, name is %s, score of English is %.1f\n", stuarray[pos].studentID, stuarray[pos].studentName, stuarray[pos].score[1]);
    return 0;
}

void input(STUDENT stu_inf[], int n)
{
    printf("Please enter students' massage:\n");
    for (int i = 0; i < n; i++) // 遍历学生个数
    {
        printf("student's ID Name:\n");
        scanf(" %ld", &stu_inf[i].studentID);
        scanf(" %s", stu_inf[i].studentName);
        for (int j = 0; j < 3; j++) // 遍历课程数目
        {
            printf("The Score of Course %s:\n", CourseName[j]);
            scanf("%f", &stu_inf[i].score[j]); // 课程分数和课程名称的下标一致
        }
    }
    return;
}

void average(STUDENT stu_inf[], int n, float ave_course[])
{
    double sum;                 // double类型保障数据不易改变
    for (int i = 0; i < 3; i++) // 遍历初始化为0
    {
        ave_course[i] = 0;
    }
    for (int i = 0; i < 3; i++)
    {
        sum = 0; // 初始化课程总分
        for (int j = 0; j < n; j++)
        {
            sum += stu_inf[j].score[i]; // 将不同学生的统一科目成绩累加
        }
        ave_course[i] = (double)(sum / n); // 强制类型转化为double类型成绩的数值不易改变，而且平均分很有可能是小数
    }
    return;
}

void PrintCourseAverage(float ave_course[], int m)
{
    for (int i = 0; i < m; i++) // 遍历课程名称和课程平均分，两者所在的数组下标一一对应
    {
        printf("Average score for course %s is %.2f\n", CourseName[i], ave_course[i]);
    }
    return;
}

int find(STUDENT stu_inf[], int n, int key)
{
    int left = 0;         // right,left,mid都表示元素的下标
    int right = n - 1;    // 注意一共有n个元素，但是第一个元素标号为0，所以最后一个元素的下标为n-1
    while (left <= right) // 循环的标志
    {
        int mid = left + (right - left) / 2; // 取中间值的方法，防止right+left太大，超过类型的范围造成数值溢出
        if (stu_inf[mid].studentID == key)
        {
            return mid;
        }
        else if (stu_inf[mid].studentID < key)
        {
            left = mid + 1;
        }
        else
        {
            right = mid - 1;
        }
    }
    return -1; // 没有找到返回-1
}